; 1 Local State Variable

; set!
; in order to have object whose internal state is changed with time
; assignment is necessary, which is done by set!

(define balance 50)
(set! balance 100)

balance

; begin
; now the sequence is important
; we have (begin <exp1> ... <expk>) to exec in sequence; <expk> as the return val
(define (withdraw money)
    (if (<= money balance)
        (begin 
            (set! balance (- balance money))
            balance ; return the remaining money
        )
        "Insufficient Funds!"
    )
)
(withdraw 20)
(withdraw 150)

; use let to make state varibable internal
(define new-withdraw 
    (let ((balance 100))
        (lambda (money) 
            (if (<= money balance)
            (begin 
                (set! balance (- balance money))
                balance ; return the remaining money
            )
            "Insufficient Funds!"    
            )
        ) 
    )
)
(new-withdraw 50)
(new-withdraw 60)

; or use paramters(which is already local)
(define (make-withdrawer balance)
    (lambda (money) 
        (if (<= money balance)
            (begin 
                (set! balance (- balance money))
                balance ; return the remaining money
            )
            "Insufficient Funds!"    
        )
    )
)
(define withdraw_20 (make-withdrawer 20))
(withdraw_20 100)
(withdraw_20 10)

; in last part, we essentially create an object, but only with one method
; using message-passing style, we can have multiple methods
(define (make-account balance)
    (define (withdraw money)
        (if (<= money balance)
            (begin 
                (set! balance (- balance money))
                balance ; return the remaining money
            )
            "Insufficient Funds!"    
        )
    )
    (define (deposit money)
        (begin 
            (set! balance (+ balance money))
            balance
        )
    ) 
    (define (dispatch m)
        (cond ((eq? m 'withdraw ) withdraw)
            ((eq? m 'deposit) deposit))
    )
    dispatch
)
(define withdraw_50 (make-account 50))
( (withdraw_50 'withdraw) 10)
( (withdraw_50 'withdraw) 10)
( (withdraw_50 'deposit) 10)

; 2 the benefit of introducing assignment
; From the point of view of one part of a complex process, the other parts appear to change with time


; 3 the cost of introducing assignment
; substitution is based ultimately on the notion that 
; the symbols in our language are essentially names for values
; But as soon as we introduce set! and the idea that the value of a variable can change, 
; a variable can no longer be simply a name

; Now a variable somehow refers to a place where a value can be stored, 
; and the value stored at this place can change

; Reasoning about same

; 1. indentity
; two object can have same state var, 
; but we still regard them to be two object
; which means there are other var to determine the identity(e.g. address, or numbering, ...)

; 2. 'same' issue only because of change
; if we promise never change the object, 
; the discussion will only be a moot, 
; we can state var to disdinguish, and same state var means same object

; 3 alias
; we can give same object different name, which is called alias
; which may lead to severe bug, and need to pay special attention

